#本脚本的任务是通过蓝牙获取小米温湿度计2的的温湿度和电池传感器数据。
#本文代码，参考自 https://blog.csdn.net/m0_49475727/article/details/115401631
#需要提前安装sudo apt-get install git build-essential libglib2.0-dev
from bluepy import btle
from dataclasses import dataclass
from tinydb import TinyDB, Query
import datetime
import random
import os,sys

#路径的设定，确保在各种路径下，都能正常运转
current_path=os.path.dirname(sys.argv[0])
if current_path=='':
    current_path='./'
os.chdir(current_path)

#读取配置文件,下面是一个配置文件的样例,包含蓝牙mac地址，最高温，最高湿度，最低电池容量，网页标题，邮件等一系列的信息，需要转存为"config.json"文件，是拿tinydb写的
'''
{"_default": {"1": {"id": 1, "MAC": "A4:C1:38:50:6E:28", "tmp_max": "32", "hmt_max": "88", "baterry": "15", "title": "\u5357\u660c\u5c0f\u7c73\u6e29\u6e7f\u5ea6\u8ba1", "NTP": "10.102.2.1", "sender": "nan1_IT_room@xxx.com", "receivers": "jianbo.wang@xxx.com", "mail_server": "10.4.172.3", "email_title": "\u73af\u5883\u5f02\u5e38\u8bf7\u5173\u6ce8", "email_content": "\u6ce8\u610f", "battery": "10"}}}
'''

#读取配置文件中的各类重要信息，如蓝牙mac地址，邮箱等
config = TinyDB('config.json')
config_data=config.all()
print(config_data[0]['MAC'])
mac = config_data[0]['MAC']
tmp_max=int(config_data[0]['tmp_max'])
hmt_max=int(config_data[0]['hmt_max'])
baterry=int(config_data[0]['baterry'])
sender=config_data[0]['sender']
receivers=config_data[0]['receivers']
name_title=config_data[0]['title']
print(tmp_max,hmt_max,baterry)

#获取蓝牙数据的代码，抄的
@dataclass
class Result:
    temperature: float
    humidity: int
    voltage: float
    battery: int = 0

class Measure(btle.DefaultDelegate):
    def __init__(self, params):
        btle.DefaultDelegate.__init__(self)
    
    def handleNotification(self, cHandle, data):
        try:
            result = Result(0,0,0,0)
            temp=int.from_bytes(data[0:2],byteorder='little',signed=True)/100
            humidity=int.from_bytes(data[2:3],byteorder='little')
            voltage=int.from_bytes(data[3:5],byteorder='little') / 1000
            battery = round((voltage - 2) / (3.261 - 2) * 100, 2)
            result.temperature = temp
            result.humidity = humidity
            result.voltage = voltage
            result.battery = battery
            print('hello',result)
            self.ret=result
        except Exception as e:
            print(e)
    def get_result(self):
        return self.ret

#方东改造后的获取数据的函数
def get_data(mac):
    p = btle.Peripheral(mac)
    p.writeCharacteristic(0x0038, b'\x01\x00', True) 
    p.writeCharacteristic(0x0046, b'\xf4\x01\x00', True)
    m = Measure("mijia")
    p.withDelegate(m)
    response = p.waitForNotifications(30000)
    #print(response)
    x=m.get_result()
#    print(x.temperature,x.humidity,x.battery)
    if response:
        p.disconnect()
    return x.temperature,x.humidity,x.battery
x0,x1,x2=get_data(mac)

#把温湿度，电池数据通过tinydb写入json
date = datetime.datetime.now().strftime("%Y-%m-%d")
db = TinyDB('history/'+date+'.json')
#User = Query()
time0 = datetime.datetime.now().strftime("%H:%M")

db.insert({'tmp': x0,'hmt': x1,"time": time0,'battery':x2})
db.close()

#获取本机地址
def get_host_ip():
    import socket
    """
    查询本机ip地址
    :return: ip
    """
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        try:
            s.connect(('8.8.8.10', 890))
        except:
            pass
        ip = s.getsockname()[0]
    finally:
        s.close()

    return ip

#内部邮件的发送方法
def internal_email():

    import smtplib
    #from email.mime.multipart import MIMEMultipart
    from email.mime.text import MIMEText
    #print ('hello')

    smtp = smtplib.SMTP()
    smtp.connect('10.4.172.3')
    #smtp.login(username, password)
    #msg = MIMEMultipart('mixed')
    #global content
    print(config_data[0]['receivers'].split(';'))
    msg = MIMEText(config_data[0]['email_content']+' 温度'+str(x0)+' 湿度'+str(x1)+' 电量'+str(x2)+' ip'+get_host_ip(), 'plain', 'utf-8')
    msg['Subject'] = config_data[0]['title']+config_data[0]['email_title']
    msg['to']=config_data[0]['receivers']
    print('sendmail...',smtp.sendmail(config_data[0]['sender'], config_data[0]['receivers'].split(';'), msg.as_string()))
    smtp.quit()
    #print ('ok',email_address,'ok1')

设定温湿度超标，电量过低的邮件报警
if x0>tmp_max:
    print("温度告警",x0,tmp_max)
    internal_email()
if x1>hmt_max:
    print("湿度告警",x1,htm_max)
    internal_email()
    print('邮件发送完成')
if x2<baterry:
    print('电量告警',x2,baterry)
    internal_email()
#    pass